//
// Created by Ivan Shynkarenka on 01.09.2016
//

#include "test.h"

#include "math/math.h"

using namespace CppCommon;

TEST_CASE("Math", "[CppCommon][Math]")
{
#if defined(_M_IX86)
    REQUIRE(Math::MulDiv64(4984198405165151231ull, 6132198419878046132ull, 9156498145135109843ull) == 3337967539561099935ull);
    REQUIRE(Math::MulDiv64(11540173641653250113ull, 10150593219136339683ull, 13592284235543989460ull) == 9223372036854775809ull);
    REQUIRE(Math::MulDiv64(449033535071450778ull, 3155170653582908051ull, 4945421831474875872ull) == 286482625873293138ull);
    REQUIRE(Math::MulDiv64(303601908757ull, 829267376026ull, 659820219978ull) == 381569328444ull);
    REQUIRE(Math::MulDiv64(449033535071450778ull, 829267376026ull, 659820219978ull) == 564348969767547451ull);
    REQUIRE(Math::MulDiv64(1234568ull, 829267376026ull, 1ull) == 1023786965885666768ull);
    REQUIRE(Math::MulDiv64(6991754535226557229ull, 7798003721120799096ull, 4923601287520449332ull) == 11073546515850664288ull);
    REQUIRE(Math::MulDiv64(9223372036854775808ull, 2147483648ull, 18446744073709551615ull) == 2147483647ull);
    REQUIRE(Math::MulDiv64(9223372032559808512ull, 9223372036854775807ull, 9223372036854775807ull) == 9223372032559808512ull);
    REQUIRE(Math::MulDiv64(9223372032559808512ull, 9223372036854775807ull, 12ull) == 11529215046426383701ull);
    REQUIRE(Math::MulDiv64(18446744073709551615ull, 18446744073709551615ull, 9223372036854775808ull) == 8589934594ull);
#else
    REQUIRE(Math::MulDiv64(4984198405165151231ull, 6132198419878046132ull, 9156498145135109843ull) == 3337967539561099935ull);
    REQUIRE(Math::MulDiv64(11540173641653250113ull, 10150593219136339683ull, 13592284235543989460ull) == 8618095846487663363ull);
    REQUIRE(Math::MulDiv64(449033535071450778ull, 3155170653582908051ull, 4945421831474875872ull) == 286482625873293138ull);
    REQUIRE(Math::MulDiv64(303601908757ull, 829267376026ull, 659820219978ull) == 381569328444ull);
    REQUIRE(Math::MulDiv64(449033535071450778ull, 829267376026ull, 659820219978ull) == 564348969767547451ull);
    REQUIRE(Math::MulDiv64(1234568ull, 829267376026ull, 1ull) == 1023786965885666768ull);
    REQUIRE(Math::MulDiv64(6991754535226557229ull, 7798003721120799096ull, 4923601287520449332ull) == 11073546515850664288ull);
    REQUIRE(Math::MulDiv64(9223372036854775808ull, 2147483648ull, 18446744073709551615ull) == 1073741824ull);
    REQUIRE(Math::MulDiv64(9223372032559808512ull, 9223372036854775807ull, 9223372036854775807ull) == 9223372032559808512ull);

    // Might overflow
    uint64_t overflow = Math::MulDiv64(9223372032559808512ull, 9223372036854775807ull, 12ull);
    REQUIRE(((overflow == 11529215046426383701ull) || (overflow == 0xFFFFFFFFFFFFFFFFull)));
    overflow = Math::MulDiv64(18446744073709551615ull, 18446744073709551615ull, 9223372036854775808ull);
    REQUIRE(((overflow == 18446744073709551612ull) || (overflow == 0xFFFFFFFFFFFFFFFFull)));
#endif
}
